Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix asset route caching #1002

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

vorban
Copy link

@vorban vorban commented Jan 17, 2025

This addresses #998 .

Before: php artisan route:cache serializes through reflection the route callbacks, hardwiring the execution context's absolute path to flux's asset files (ex: /Users/vorban/repositories/...) because of __DIR__ resolution.

After: php artisan route:cache serializes references to the route actions, preventing any resolution of __DIR__ before runtime.

I've tested it locally. The routes are listed by artisan route:list, and artisan route:cache correctly serialized references to the functions.

After a route:cache, going to any page that uses the blade directives like @fluxStyles works and the files are correctly fetched.

I'd prefer this to be thoroughly reviewed, as I failed to find the contribution guidelines and test suites to run.

@joshhanley
Copy link
Member

joshhanley commented Jan 22, 2025

@vorban thanks for the PR! I made a couple of small changes but all looks good to me.

The scenario

Currently, if you run php artisan route:cache during a Laravel Vapor deploy, the routes are compiled and cached locally before it is pushed to Vapor. This then causes a 500 error when trying to load Flux's assets.

The problem

What is happening is that Flux's asset routes are currently registered using closures. For example:

Route::get('/flux/flux.css', function () {
    return Flux::pro()
        ? $this->pretendResponseIsFile(__DIR__.'/../../flux-pro/dist/flux.css', 'text/css')
        : $this->pretendResponseIsFile(__DIR__.'/../../flux/dist/flux-lite.css', 'text/css');
});

So when these closures are serialised, PHP actually converts the __DIR__ to an actual path, and then that is stored in the route cache. Here is what the above route looks like compiled on my machine.

    'generated::BgAuGLqPz9H8AUEs' => 
    array (
      ...
      'uri' => 'flux/flux.css',
      'action' => 
      array (
        'uses' => 'O:55:"Laravel\\SerializableClosure\\UnsignedSerializableClosure":1:{s:12:"serializable";O:46:"Laravel\\SerializableClosure\\Serializers\\Native":5:{s:3:"use";a:0:{}s:8:"function";s:334:"function () {
            return \\Flux\\Flux::pro()
                ? $this->pretendResponseIsFile(\'/Users/josh/Development/packages/flux/src\'.\'/../../flux-pro/dist/flux.css\', \'text/css\')
                : $this->pretendResponseIsFile(\'/Users/josh/Development/packages/flux/src\'.\'/../../flux/dist/flux-lite.css\', \'text/css\');
        }";s:5:"scope";s:17:"Flux\\AssetManager";s:4:"this";O:17:"Flux\\AssetManager":0:{}s:4:"self";s:32:"00000000000004670000000000000000";}}',
        'as' => 'generated::BgAuGLqPz9H8AUEs',
      ),
      '...
    ),

As you can see above, the path from my local machine /Users/josh/Development/packages/flux/src is hardcoded into the cache.

The solution

The solution submitted by @vorban is to remove the closures and actually make methods on the AssetManager class for the different asset routes.

Route::get('/flux/flux.css', [static::class, 'fluxCss']);

...

public function fluxCss() {
    return Flux::pro()
        ? $this->pretendResponseIsFile(__DIR__.'/../../flux-pro/dist/flux.css', 'text/css')
        : $this->pretendResponseIsFile(__DIR__.'/../../flux/dist/flux-lite.css', 'text/css');
}

By doing this, the compile route now looks like this.

    'generated::NsQPI42I75o5heuR' => 
    array (
      ...
      'uri' => 'flux/flux.css',
      'action' => 
      array (
        'uses' => 'Flux\\AssetManager@fluxCss',
        'controller' => 'Flux\\AssetManager@fluxCss',
        'as' => 'generated::NsQPI42I75o5heuR',
      ),
      ...
    ),

Now we can see that the route references the fluxCss() method on the AssetManager and no longer hard codes a path.

Fixes #998

@joshhanley joshhanley changed the title fix #998 : prevent caching of route callbacks Fix asset route caching Jan 22, 2025
@joshhanley joshhanley linked an issue Jan 22, 2025 that may be closed by this pull request
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Flux js and css routes crash after artisan optimize
2 participants